/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.util.Vector;

/**
 *
 * @author
 * Abraão de Santana
 * Jorge Thiago
 * Leandro C. Arantes
 */
public class Memoria {
// Classe que gerencia a memória

    private int tamanho = -1;
    private int espacoSemBloco = -1;
    private Vector<BlocoMemoria> blocos = new Vector<BlocoMemoria>();

    public Memoria(int tamanho) {
    // Define o tamanho da memória
        this.tamanho = tamanho;
        this.espacoSemBloco = tamanho;
    }

    public int getCapacidade() {
    // Define a capacidade da memória.

        return tamanho;
    }

    public void setCapacidade(int capacidade) {
    // Configura a capacidade da memória.
        this.tamanho = capacidade;
    }

    public boolean addProcesso(Processo processo) {
    // Adiciona um processo na memória.

        int espacoRequerido = processo.getmBytes();
        int espacoVazio = getEspacoVazio();
        if (espacoVazio >= espacoRequerido) {
        // verifica se o espaço vazio é maior que o necessário, sendo, executa

            BlocoMemoria blocoVazio = getBlocoVazio(espacoRequerido);
            if (blocoVazio != null) {
                int espacoRestante = blocoVazio.getTamanho() - espacoRequerido;
                espacoSemBloco += espacoRestante;
                blocoVazio.setTamanho(espacoRequerido);
                blocoVazio.setProcesso(processo);
                blocoVazio.setOcupado(true);
                return true;
            } // Fim if blocoVazio
            else {
            // else do if blocoVazio
                BlocoMemoria bloco = new BlocoMemoria(processo);
                espacoSemBloco -= processo.getmBytes();
                blocos.add(bloco);
                return true;
            } //Fim do else
        } // Fim do IF espaço vazio.

        return false;
    } // Fim da função adiciona processo

    public int getEspacoVazio()
    // Retorna o tamanho total livre da memória.
    {
        int totalVazio = 0; // total de espaço vazio

        int blocoVazio = 0;
        for (BlocoMemoria bloco : blocos) {
            if (!bloco.ocupado()) {
            //Se o bloco NÃO estiver ocupado, ele recebe o blocoVazio mais
            //o tamanho do bloco atual
                blocoVazio += bloco.getTamanho();
            }
        }

        totalVazio = espacoSemBloco + blocoVazio;

        return totalVazio;
    }

    private BlocoMemoria getBlocoVazio(int mBytes) {
    // procura o primeiro bloco vazio, e o retorna
        for (BlocoMemoria bloco : blocos) {
        //percorre os blocos
            if (!bloco.ocupado() && bloco.getTamanho() > mBytes) {
                return bloco;
            } // fim IF
        } // fim do for

        return null;
    } // fim do procedimento BlocoMemória

    public Processo exchangeProcesses(Processo processo) {
    // Coloca o processo em estado suspenso

        Processo processoSuspenso = null;
        for (BlocoMemoria bloco : blocos) {
            processoSuspenso = bloco.getProcesso();
            if (processoSuspenso.getPrioridade() != 0 &&
                    processoSuspenso.getmBytes() > processo.getmBytes() &&
                    processoSuspenso.getEstado().equals(Processo.PRONTO))
            {
                bloco.setProcesso(processo);
                espacoSemBloco += (bloco.getTamanho() - processo.getmBytes());
                bloco.setTamanho(processo.getmBytes());
                return processoSuspenso;
            } // Fim do IF
        } // Fim do FOR

        return null;
    }

    public void removerProcesso(Processo processoAtivo) {
    // Remove o processo da memória e deixa o espaço ocupado por ele, livre

        for (BlocoMemoria bloco : blocos) {
            if (bloco.ocupado() && processoAtivo.getId() == bloco.getProcesso().getId()) {
                bloco.setOcupado(false);
                return;
            } // Fim fo IF
        } // Fim do FOR
    } // Fim do procedimento removerProcesso

    public boolean contemProcesso(Processo process) {
    // Verifica se o bloco contém algum processo

        for (BlocoMemoria block : blocos) {
            if (block.ocupado() && process.getId() == block.getProcesso().getId()) {
                return true;
            } // Fim do IF
        } // Fim do FOR

        return false;
    } // Fim da função contemProcesso
}
